import * as nacos from 'nacos';
import {ConfigManager, loadConfigByLocalEnv, SharedConfig} from './configManager';
import LoadBalanceHttpClient from './loadBalanceHttpClient';
import * as networkInterfaces from './networkInterfaces';

export const nacosHost = loadConfigByLocalEnv('nacos.hostname'); // 系统环境变量 NACOS_HOSTNAME
export const nacosPort = loadConfigByLocalEnv('nacos.port'); // 系统环境变量 NACOS_PORT
export const namespace = loadConfigByLocalEnv('nacos.namespace', ''); // 系统环境变量 NACOS_NAMESPACE
export const configSharedConfigs = loadConfigByLocalEnv('nacos.config.sharedConfigs'); // 系统环境变量 NACOS_CONFIG_SHAREDCONFIGS
export const appName = loadConfigByLocalEnv('app.name', 'nodejs-application');
export const version = loadConfigByLocalEnv('app.version', '');
export const clientIp = networkInterfaces.getNetworkInterface({family: 'IPv4'}).address;
export const metadata: { [key: string]: any } = {'preserved.register.source': 'NODEJS_NESTJS', version};
const serverAddr = nacosHost + (nacosPort ? ':' + nacosPort : '');
export const loadBalanceHttpClient = new LoadBalanceHttpClient();

export const nacosConfigClient = new nacos.NacosConfigClient({
  serverAddr: serverAddr,
  namespace: namespace
});
export const nacosNamingClient = new nacos.NacosNamingClient({
  logger: console,
  serverList: serverAddr,
  namespace: namespace
});

/**
 * config client
 */
let configManager = null;

export function getConfigManager(): ConfigManager {
  if (configManager === null) {
    configManager = new ConfigManager(nacosConfigClient);
    const configs: SharedConfig[] = configSharedConfigs.split(',').concat(appName + '.yml').map((dataId) => {
      return {dataId, refresh: true};
    });
    configManager.addConfigs(configs);
  }
  return configManager;
}

/**
 * naming client
 */
export interface InstanceOption {
  ip: string,
  port: string,
  metadata: { [key: string]: any };
}

export let currentInstance = null;
async function buildInstance(): Promise<InstanceOption> {
  let port = parseInt(await configManager.getConfig('server.port'));

  if (isNaN(port) || port <= 0) {
    port = Math.floor(Math.random() * 1000 + 30000);
  }

  return {
    ip: clientIp,
    port: '' + port,
    metadata
  };
}
export async function registerInstance(): Promise<InstanceOption> {
  return buildInstance().then((instance) => {
    currentInstance = instance;
    nacosNamingClient.registerInstance(appName, instance);
    return instance;
  });
}
export function deregisterInstance() {
  if (currentInstance) {
    nacosNamingClient.deregisterInstance(appName, currentInstance);
  }
}
